#include "tilemap.hpp"
#include <cassert>
#include "tileset.hpp"
#include "canvas.hpp"

namespace yep
{
Tilemap::Tilemap()
{
	mapWidth = mapHeight = 0;
	tileset = nullptr;
}

Tilemap::Tilemap(Tileset &tileset_, unsigned mapWidth_, unsigned mapHeight_)
{
	mapWidth = mapWidth_;
	mapHeight = mapHeight_;
	tileset = &tileset_;
}

template<class T>
Tilemap::Tilemap(Tileset &tileset_, unsigned mapWidth_, T iteratorBegin, T iteratorEnd) :
		tiles(iteratorBegin, iteratorEnd)
{
	tileset = &tileset_;
	mapWidth = mapWidth_;
}

Tilemap::Tilemap(const initializer_list<int>& list) :
		tiles(list)
{
	mapWidth = mapHeight = 0;
	tileset = NULL;
}

Tilemap::~Tilemap()
{
}

int &Tilemap::operator[](const Vector2 &position)
{
	size_t index = position.y * mapWidth + position.x;
	YEP_ASSERT( index < mapWidth * mapHeight);
	return tiles[index];
}

Tilemap &Tilemap::setMapWidth(unsigned value)
{
	YEP_ASSERT( mapWidth == 0);
	mapWidth = value;
	return *this;
}

Tilemap &Tilemap::setMapHeight(unsigned value)
{
	YEP_ASSERT( mapHeight == 0);
	mapHeight = value;
	return *this;
}

Tilemap &Tilemap::setTileset(Tileset &value)
{
	YEP_ASSERT( tileset == NULL);
	tileset = &value;
	return *this;
}

void Tilemap::draw(Canvas &canvas, const Vector2 &position)
{
	YEP_ASSERT( tileset != NULL);
	unsigned tileWidth = tileset->getTileWidth();
	unsigned tileHeight = tileset->getTileHeight();
	for (unsigned y = 0; y < mapHeight; ++y)
		for (unsigned x = 0; x < mapWidth; ++x)
		{
			int tile = tiles[y * mapWidth + x];
			if (tile > 0)
				tileset->draw(canvas, position + Vector2(x * tileWidth, y * tileHeight), tiles[y * mapWidth + x] - 1);
		}
}

void Tilemap::draw(Canvas &canvas, const Vector2 &position, const Vector2 &sectionPosition, const Vector2 &sectionSize)
{
	YEP_ASSERT( tileset != NULL);
//    cerr << "Sorry. We didn't implement it yet" << endl;
//    exit(EXIT_FAILURE);

	unsigned tileWidth = tileset->getTileWidth();
	unsigned tileHeight = tileset->getTileHeight();

	canvas.setClipArea(position, sectionSize);
	for (unsigned y = 0; y < mapHeight; ++y)
	{
		for (unsigned x = 0; x < mapWidth; ++x)
		{
			int tile = tiles[y * mapWidth + x];
			if (tile > 0)
				tileset->draw(canvas, position + Vector2(x * tileWidth, y * tileHeight) - sectionPosition,
						tiles[y * mapWidth + x] - 1);
		}
	}
	canvas.clearClipArea();

}

}
